package com.meal.entity.aspect;

import com.meal.entity.base.BaseController;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;

/**
 * @AspectJ提供不同的通知类型
 *
 * ····@Before前置通知，相当于BeforeAdvice
 *
 * ····@AfterReturning后置通知，相当于AfterReturningAdvice
 *
 * ····@Around环绕通知，相当于MethodInterceptor
 *
 * ····@AfterThrowing抛出通知，相当于ThrowAdvice
 *
 * ····@After最终final通知，不管是否异常，该通知都会执行
 */
/**
 * 注解方式声明aop
 * 1.用@Aspect注解将类声明为切面(如果用@Component("")注解注释为一个bean对象，那么就要在spring配置文件中开启注解扫描，<context:component-scan base-package="com.cjh.aop2"/>
 *      否则要在spring配置文件中声明一个bean对象)
 * 2.在切面需要实现相应方法的前面加上相应的注释，也就是通知类型。
 * 3.此处有环绕通知，环绕通知方法一定要有ProceedingJoinPoint类型的参数传入，然后执行对应的proceed()方法，环绕才能实现。
 */
@Aspect
@Component
@Log4j
public class ValidParamAspect extends BaseController {

    //定义切点
    @SneakyThrows
    @Around(value = "@annotation(com.meal.entity.annotation.ValidParam)")
    public Object around(ProceedingJoinPoint joinPoint) {
        for (Object obj : joinPoint.getArgs()) {
            if (obj instanceof BindingResult){
                BindingResult bindingResult = (BindingResult) obj;
                if (bindingResult.hasErrors())  return createFailedResult(bindingResult.getAllErrors().get(0).getDefaultMessage());
            }
        }
        return joinPoint.proceed();
    }
}
